<template>
  <div class="face-auth-container">
    <!-- 页面标题 -->
    <div class="page-title">
      <h3>{{ isRegistering ? '人脸注册' : '人脸登录' }}</h3>
    </div>
    
    <!-- 摄像头预览区域 -->
    <div class="camera-preview">
      <video ref="videoElement" autoplay playsinline class="camera-feed"></video>
      <canvas ref="canvasElement" class="capture-canvas"></canvas>
      <!-- 摄像头未启动状态 -->
      <div v-if="!cameraActive && !processing && !cameraLoading" class="camera-placeholder">
        <i class="el-icon-video-camera"></i>
        <p>请点击"启动摄像头"按钮开始</p>
      </div>
      <!-- 摄像头加载中状态 -->
      <div v-if="cameraLoading && !cameraActive" class="camera-loading">
        <div class="el-loading-spinner">
          <svg class="circular" viewBox="25 25 50 50">
            <circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle>
          </svg>
        </div>
        <p>正在启动摄像头...</p>
      </div>
    </div>
    
    <!-- 操作按钮 -->
    <div class="controls">
      <el-button 
        type="primary" 
        @click="initCamera" 
        :disabled="cameraActive || processing || cameraLoading"
        class="control-btn"
      >
        <i class="el-icon-video-camera"></i> 启动摄像头
      </el-button>
      
      <el-button 
        type="success" 
        @click="captureFace" 
        :disabled="!cameraActive || processing || !!capturedImage || cameraLoading"
        class="control-btn"
      >
        <i class="el-icon-camera"></i> 拍摄人脸
      </el-button>
      
      <el-button 
        type="warning" 
        @click="stopCamera" 
        :disabled="!cameraActive || processing || cameraLoading"
        class="control-btn"
      >
        <i class="el-icon-video-close"></i> 关闭摄像头
      </el-button>
    </div>
    
    <!-- 模式切换 -->
    <div class="mode-switch">
      <el-radio-group v-model="isRegistering" size="small">
        <el-radio-button :label="false">人脸登录</el-radio-button>
        <el-radio-button :label="true">人脸注册</el-radio-button>
      </el-radio-group>
    </div>
    
    <!-- 注册表单（仅注册模式显示） -->
    <div v-if="isRegistering" class="registration-form">
      <el-form :model="registerForm" :rules="registerRules" ref="registerForm" label-width="80px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="registerForm.username" placeholder="请输入用户名"></el-input>
        </el-form-item>
        <el-form-item label="手机号" prop="phonenumber">
          <el-input v-model="registerForm.phonenumber" placeholder="请输入手机号"></el-input>
        </el-form-item>
        <el-form-item label="所属部门" prop="deptId">
          <el-select v-model="registerForm.deptId" placeholder="请选择部门" :disabled="deptLoading">
            <el-option 
              v-for="dept in deptOptions" 
              :key="dept.value" 
              :label="dept.label" 
              :value="dept.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input type="password" v-model="registerForm.password" placeholder="请输入密码"></el-input>
        </el-form-item>
      </el-form>
    </div>
    
    <!-- 结果展示 -->
    <div class="result-display">
      <!-- 捕获的人脸预览 -->
      <div v-if="capturedImage && !processing && !cameraLoading" class="captured-image">
        <p class="preview-title">人脸预览</p>
        <img :src="capturedImage" alt="捕获的人脸" class="face-img">
        <div class="action-buttons">
          <el-button 
            type="primary" 
            @click="confirmFace"
            :loading="processing"
          >
            {{ isRegistering ? '确认注册' : '确认登录' }}
          </el-button>
          <el-button @click="retryCapture">重新拍摄</el-button>
        </div>
      </div>
      
      <!-- 处理中状态 -->
      <div v-if="processing" class="processing-indicator">
        <el-progress type="circle" :percentage="progress" :width="80"></el-progress>
        <p class="processing-text">正在{{ isRegistering ? '注册' : '验证' }}人脸...</p>
      </div>
      
      <!-- 结果消息 -->
      <el-alert
        v-if="resultMessage"
        :title="resultMessage"
        :type="resultSuccess ? 'success' : 'error'"
        show-icon
        class="result-alert"
      ></el-alert>
    </div>
    
    <!-- 回到账号密码登录 -->
    <div class="back-to-login">
      <el-link type="primary" @click="$router.push('/login')">
        <i class="el-icon-arrow-left"></i> 返回账号密码登录
      </el-link>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import { Message } from 'element-ui'
import axios from '@/utils/request'
import { getToken, setToken, removeToken } from '@/utils/auth'

export default {
  name: 'FaceLogin',
  data() {
    return {
      // DOM元素引用
      videoElement: null,
      canvasElement: null,
      // 业务状态
      cameraActive: false,
      cameraLoading: false,
      isRegistering: false,
      capturedImage: null,
      processing: false,
      progress: 0,
      resultMessage: '',
      resultSuccess: false,
      stream: null,
      progressInterval: null,
      // 部门列表
      deptOptions: [
        { label: '研发部', value: '103' },
        { label: '市场部', value: '104' },
        { label: '人事部', value: '105' },
        { label: '财务部', value: '106' }
      ],
      deptLoading: false,
      // 注册表单数据
      registerForm: {
        username: '',
        phonenumber: '',
        password: '',
        deptId: '',
        status: '0',
        nickname: '',
        email: ''
      },
      // 注册表单验证规则
      registerRules: {
        username: [
          { required: true, message: '请输入用户名', trigger: 'blur' },
          { min: 2, max: 20, message: '用户名长度在 2 到 20 个字符', trigger: 'blur' }
        ],
        phonenumber: [
          { required: true, message: '请输入手机号', trigger: 'blur' },
          { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号', trigger: 'blur' }
        ],
        deptId: [
          { required: true, message: '请选择所属部门', trigger: 'change' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' },
          { min: 6, max: 20, message: '密码长度在 6 到 20 个字符', trigger: 'blur' }
        ]
      },
      // 重定向地址
      redirect: this.$route.query.redirect || '/',
      // 存储当前登录用户ID
      currentUserId: null
    }
  },
  computed: {
    // 人脸登录页无需额外 Vuex getter
  },
  created() {
    // 已登录用户直接跳转首页
    if (getToken()) {
      this.$router.push('/index').catch(() => {})
      return
    }
    // 默认选中第一个部门
    if (this.deptOptions.length > 0) {
      this.registerForm.deptId = this.deptOptions[0].value
    }
  },
  mounted() {
    // 初始化DOM引用
    this.videoElement = this.$refs.videoElement
    this.canvasElement = this.$refs.canvasElement
  },
  beforeDestroy() {
    // 组件销毁时清理资源
    this.stopCamera()
    if (this.progressInterval) clearInterval(this.progressInterval)
  },
  methods: {
    // 初始化摄像头
    async initCamera() {
      try {
        this.resultMessage = ''
        this.cameraLoading = true
        
        // 请求摄像头权限
        this.stream = await navigator.mediaDevices.getUserMedia({
          video: {
            width: { ideal: 640 },
            height: { ideal: 480 },
            facingMode: 'user'
          }
        })
        
        this.videoElement.srcObject = this.stream
        this.cameraActive = true
      } catch (error) {
        let errorMsg = '摄像头访问失败: '
        if (error.name === 'NotAllowedError') {
          errorMsg += '请授予摄像头权限'
        } else if (error.name === 'NotFoundError') {
          errorMsg += '未检测到可用摄像头'
        } else if (error.name === 'NotSupportedError') {
          errorMsg += '当前环境不支持摄像头访问，请使用HTTPS或localhost'
        } else {
          errorMsg += error.message
        }
        Message.error(errorMsg)
        console.error('摄像头初始化失败:', error)
      } finally {
        this.cameraLoading = false
      }
    },

    // 停止摄像头
    stopCamera() {
      if (this.stream) {
        this.stream.getTracks().forEach(track => track.stop())
        this.stream = null
      }
      this.cameraActive = false
      this.capturedImage = null
    },

    // 捕获人脸
    captureFace() {
      if (!this.cameraActive || this.cameraLoading) {
        Message.warning('请先完成摄像头启动')
        return
      }

      const canvas = this.canvasElement
      const video = this.videoElement
      
      // 处理视频尺寸为0的异常情况
      const canvasWidth = video.videoWidth || 640
      const canvasHeight = video.videoHeight || 480
      canvas.width = canvasWidth
      canvas.height = canvasHeight
      
      // 绘制视频帧到canvas
      const ctx = canvas.getContext('2d')
      ctx.drawImage(video, 0, 0, canvasWidth, canvasHeight)
      
      // 存储Base64图片
      this.capturedImage = canvas.toDataURL('image/jpeg', 0.8)
    },

    // 重新拍摄
    retryCapture() {
      this.capturedImage = null
      this.resultMessage = ''
    },

    // 确认人脸操作
    async confirmFace() {
      if (this.isRegistering) {
        // 注册模式：先验证表单
        this.$refs.registerForm.validate(async (valid) => {
          if (valid) {
            await this.registerFace()
          }
        })
      } else {
        // 登录模式：直接调用接口
        await this.loginWithFace()
      }
    },

    // 人脸注册
    async registerFace() {
      this.processing = true
      this.resultMessage = ''
      this.progress = 0

      try {
        // 补充昵称和邮箱
        this.registerForm.nickname = this.registerForm.nickname || this.registerForm.username
        this.registerForm.email = this.registerForm.email || this.registerForm.username + '@example.com'

        // 清除旧定时器
        if (this.progressInterval) clearInterval(this.progressInterval)
        // 启动进度条
        this.progressInterval = setInterval(() => {
          if (this.progress < 90) {
            this.progress += 10
          }
        }, 200)

        // 调用后端人脸注册接口
        const response = await axios.post('/face/register', {
          ...this.registerForm,
          faceImage: this.capturedImage ? this.capturedImage.split(',')[1] : ''
        })

        // 完成进度并清除定时器
        clearInterval(this.progressInterval)
        this.progress = 100

        if (response.code === 200) {
          this.resultSuccess = true
          this.resultMessage = `人脸注册成功，用户名：${this.registerForm.username}`
          // 重置状态，切换到登录模式
          setTimeout(() => {
            this.isRegistering = false
            this.retryCapture()
            this.$refs.registerForm.resetFields()
            // 重置后默认选中第一个部门
            if (this.deptOptions.length > 0) {
              this.registerForm.deptId = this.deptOptions[0].value
            }
          }, 1500)
        } else {
          this.resultSuccess = false
          this.resultMessage = response.msg || '人脸注册失败'
        }
      } catch (error) {
        clearInterval(this.progressInterval)
        this.resultSuccess = false
        this.resultMessage = error.msg || '注册失败，请重试'
      } finally {
        setTimeout(() => {
          this.processing = false
          this.progress = 0
        }, 500)
      }
    },

    // 人脸登录 - 完整修复版本
    async loginWithFace() {
      this.processing = true
      this.resultMessage = ''
      this.progress = 0

      try {
        if (this.progressInterval) clearInterval(this.progressInterval)
        this.progressInterval = setInterval(() => {
          if (this.progress < 90) {
            this.progress += 10
          }
        }, 200)

        // 1. 调用人脸登录接口，获取用户名、token和用户ID
        const faceLoginRes = await axios.post('/face/login', {
          faceImage: this.capturedImage ? this.capturedImage.split(',')[1] : ''
        })

        if (faceLoginRes.code !== 200) {
          throw new Error(faceLoginRes.msg || '人脸验证失败')
        }

        // 2. 从接口返回中获取关键信息（确保包含userId）
        const { username, token } = faceLoginRes.data // 不再需要 userId
        if (!username || !token) {
          throw new Error('人脸登录失败：返回数据不完整')
        }
        // 3. 保存 Token（Vuex permission 流程依赖）
        setToken(token)
        this.$store.commit('SET_TOKEN', token) // 同步写入 Vuex，关键修复
        
        // 4. 按传统登录流程获取用户信息并生成路由
        await this.$store.dispatch('GetInfo')
        await this.$store.dispatch('GenerateRoutes')
        
        // 5. 登录成功跳转首页
        clearInterval(this.progressInterval)
        this.progress = 100
        this.$router.replace(this.redirect || '/index').then(() => {
          this.resultSuccess = true
          this.resultMessage = '人脸登录成功，已加载权限模块'
        })

      } catch (error) {
        clearInterval(this.progressInterval)
        this.resultSuccess = false
        this.resultMessage = error.message || '登录失败，请重试'
        removeToken() // 清除无效Token
        this.$router.push('/login')
      } finally {
        setTimeout(() => {
          this.processing = false
          this.progress = 0
        }, 500)
      }
    }
  }
}
</script>

<style scoped>
.face-auth-container {
  max-width: 600px;
  margin: 50px auto;
  padding: 30px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  font-family: "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
}

.page-title {
  text-align: center;
  margin-bottom: 25px;
  padding-bottom: 15px;
  border-bottom: 1px solid #f0f0f0;
}

.page-title h3 {
  font-size: 22px;
  color: #1f2d3d;
  margin: 0;
  font-weight: 500;
}

.camera-preview {
  position: relative;
  width: 100%;
  height: 400px;
  margin-bottom: 25px;
  border: 1px solid #e5e6e7;
  border-radius: 6px;
  overflow: hidden;
  background-color: #f3f3f3;
  transition: all 0.3s ease;
}

.camera-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: #888;
  background-color: #fafafa;
  transition: all 0.3s ease;
}

.camera-placeholder i {
  font-size: 56px;
  margin-bottom: 15px;
  color: #c0c4cc;
}

.camera-placeholder p {
  font-size: 16px;
  margin: 0;
}

.camera-loading {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  background-color: rgba(255, 255, 255, 0.8);
  z-index: 10;
}

.el-loading-spinner {
  width: 40px;
  height: 40px;
  position: relative;
}

.circular {
  width: 40px;
  height: 40px;
  animation: loading-rotate 2s linear infinite;
}

.path {
  stroke-dasharray: 90, 150;
  stroke-dashoffset: 0;
  stroke: #409eff;
  animation: loading-dash 1.5s ease-in-out infinite;
  stroke-linecap: round;
}

@keyframes loading-rotate {
  100% {
    transform: rotate(360deg);
  }
}

@keyframes loading-dash {
  0% {
    stroke-dasharray: 1, 200;
    stroke-dashoffset: 0;
  }
  50% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -40px;
  }
  100% {
    stroke-dasharray: 90, 150;
    stroke-dashoffset: -120px;
  }
}

.camera-loading p {
  margin-top: 15px;
  color: #409eff;
}

.camera-feed {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.capture-canvas {
  display: none;
}

.controls {
  display: flex;
  justify-content: center;
  gap: 15px;
  margin-bottom: 30px;
  flex-wrap: wrap;
}

.control-btn {
  min-width: 130px;
  padding: 10px 15px;
  transition: all 0.2s ease;
}

.mode-switch {
  text-align: center;
  margin-bottom: 25px;
  padding: 15px;
  background-color: #f5f7fa;
  border-radius: 6px;
}

.registration-form {
  margin-bottom: 25px;
  padding: 20px;
  border: 1px solid #e5e6e7;
  border-radius: 6px;
  transition: all 0.3s ease;
}

.registration-form:hover {
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}

.result-display {
  text-align: center;
  margin: 20px 0;
}

.captured-image {
  margin: 0 auto;
  max-width: 300px;
  padding: 15px;
  border-radius: 6px;
  background-color: #f9f9f9;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.preview-title {
  margin-bottom: 15px;
  color: #666;
  font-size: 15px;
  font-weight: 500;
}

.face-img {
  width: 100%;
  border: 1px solid #e5e6e7;
  border-radius: 4px;
  margin-bottom: 20px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

.action-buttons {
  display: flex;
  justify-content: center;
  gap: 15px;
}

.processing-indicator {
  margin: 30px 0;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.processing-text {
  margin-top: 20px;
  color: #409eff;
  font-size: 15px;
}

.result-alert {
  margin: 20px 0;
}

.back-to-login {
  text-align: center;
  margin-top: 25px;
  padding-top: 15px;
  border-top: 1px solid #f0f0f0;
}

@media (max-width: 768px) {
  .face-auth-container {
    margin: 20px;
    padding: 20px;
  }
  
  .camera-preview {
    height: 300px;
  }
  
  .controls {
    gap: 10px;
  }
  
  .control-btn {
    min-width: 110px;
    padding: 8px 12px;
    font-size: 13px;
  }
  
  .captured-image {
    max-width: 100%;
  }
}
</style>
